--
Limit request size and anti-DDoS tuning
Overview
Limiting request size and tuning anti-DDoS controls reduces the risk that a VPS or web server becomes unavailable due to oversized uploads, abusive clients, or high-rate traffic bursts. In a WordPress stack (often OpenLiteSpeed + PHP LSAPI + MariaDB), this typically means enforcing strict limits at multiple layers: web server request/body size, PHP upload limits, application-level protections (XML-RPC/REST abuse), and network-level rate limiting.
History
- Early web stacks relied on application code to handle uploads and request parsing, which left servers vulnerable to oversized payloads and slow-client attacks.
- As volumetric and application-layer DDoS became common, rate limiting, connection limits, and upstream filtering became standard operational controls.
- Modern stacks implement layered limits so abusive traffic is rejected early, before PHP or the database does expensive work.
Adoption
Commonly used in:
- WordPress on VPS (fixed RAM/CPU budget, high sensitivity to spikes)
- OpenLiteSpeed and NGINX/Apache deployments handling uploads and public traffic
- API endpoints and login pages frequently targeted by brute force and floods
- Sites behind CDNs or load balancers that still need origin hardening
Maintainer
Maintained by the OS distribution, web server project (OpenLiteSpeed/Apache/NGINX), and your network/CDN provider. There is no single “anti-DDoS” component.
Best when to use
- You run a public WordPress site and want safer defaults for uploads and requests
- You have limited VPS resources and need to reject abusive traffic early
- You want predictable performance under bursts (legitimate or malicious)
- You can coordinate limits across web server, PHP, and WordPress
Not suitable when
- You require large uploads without an alternate upload path (direct-to-object-storage, chunked uploads)
- You cannot tune and test limits (risk of breaking legitimate workflows)
- You expect sustained volumetric DDoS beyond what your ISP/CDN can absorb (use upstream mitigation)
Compatibility notes
- OpenLiteSpeed has its own request/body and connection controls; exact names vary by version.
- PHP limits (
upload_max_filesize,post_max_size,max_input_time,max_execution_time) must align with web server limits. - WordPress media uploads typically use HTTP POST; some plugins use chunked uploads and may require different tuning.
- If you are behind a CDN or reverse proxy, ensure you trust the correct client IP headers and do not rate-limit the proxy itself.
Setting limits too aggressively can break media uploads, plugin/theme installs, backups, REST API clients, and checkout flows. Roll out in stages and validate critical user journeys.
Threat model and where limits apply
Common abusive patterns
| Pattern | What it looks like | Primary mitigation layers |
|---|---|---|
| -- | ||
| Oversized uploads | Very large POST bodies | Web server body limits, PHP upload limits |
| Slowloris / slow clients | Many connections that send data slowly | Connection timeouts, per-IP connection limits |
| Request floods | High RPS to expensive endpoints | Rate limiting, caching, WAF, CDN |
| Login brute force | Repeated /wp-login.php attempts | Rate limits, fail2ban, CAPTCHA, 2FA |
| XML-RPC abuse | Floods to /xmlrpc.php | Disable if unused, rate limit |
| REST abuse | Floods to /wp-json/ endpoints | Cache, rate limit, WAF rules |
| Layer-7 cache bypass | Unique query strings | Cache policy, ignore query params where safe |
Layered limits (recommended hierarchy)
Enforce limits from the earliest/cheapest layer to the latest/most expensive:
- CDN / upstream network filtering (if available)
- Host firewall and kernel controls
- Web server connection/rate limits and request size limits
- PHP execution and upload limits
- WordPress/application-level protections (disable unused endpoints, login protections)
- WAF rules (ModSecurity/CRS), if deployed
Request size limits (uploads and POST bodies)
Align limits across layers
A safe alignment rule:
- Web server max request body >= PHP
post_max_size>= PHPupload_max_filesize - WordPress will fail uploads if any upstream layer is smaller.
Recommended starting values for typical WordPress sites:
| Use case | Web server max body | post_max_size | upload_max_filesize |
|---|---|---|---|
| : | --: | --: | |
| Blog / basic | 32M | 32M | 24M |
| WooCommerce | 64M | 64M | 48M |
| Media-heavy / courses | 128M | 128M | 96M |
Some plugins upload large zip archives or use chunked uploads. If you use backups/migration plugins, validate their maximum upload size requirements before lowering limits.
PHP settings (common)
Edit the relevant php.ini for LSAPI (path varies by distro and lsphp version):
upload_max_filesize = 48M
post_max_size = 64M
max_file_uploads = 20
max_input_time = 60
max_execution_time = 120
memory_limit = 768M
Verification (read-only):
php -i | grep -E 'upload_max_filesize|post_max_size|max_file_uploads|max_input_time|max_execution_time|memory_limit'
OpenLiteSpeed request body limits
OpenLiteSpeed exposes request/POST body limits in WebAdmin. Names vary by version; commonly relevant areas include:
- Server-level tuning
- Virtual Host-level settings
- Security/request filters
After changing limits, validate by uploading a file slightly below the limit and slightly above the limit to confirm behavior.
OpenLiteSpeed configuration labels differ across versions. Use the WebAdmin search (if available) for “request body”, “max request”, “upload”, or “post size” to find the effective setting.
Rate limiting and connection controls
Choose endpoints to protect first
Start with endpoints that are expensive or commonly abused:
| Endpoint | Why it matters |
|---|---|
| -- | - |
/wp-login.php | brute force, credential stuffing |
/xmlrpc.php | amplification and brute force vectors |
/wp-admin/admin-ajax.php | can be expensive, often abused |
/wp-json/ | API floods, bot traffic |
/?s= search | can trigger expensive queries |
Host-level rate limiting (iptables / nftables)
Prefer testing rules in a non-production window. The examples below show patterns; exact commands should be adapted to your firewall framework.
nftables example (conceptual)
# Example concept: limit new connections per IP to HTTP/HTTPS
# Implement in your nftables ruleset with correct table/chain names.
If you use UFW or firewalld, apply equivalent rate limits via their supported mechanisms or custom rules.
Firewall rule changes can block SSH. Ensure SSH allow rules are explicit and test from a secondary session before applying persistent changes.
Application-level protections (WordPress)
Disable XML-RPC if not needed
If you do not use Jetpack, the WordPress mobile app, or external publishing integrations, XML-RPC can often be disabled.
Web server-level block (conceptual):
- Deny access to
/xmlrpc.php
WordPress-level approach:
- Use a security plugin or a small MU-plugin to disable XML-RPC.
Disabling XML-RPC can break legitimate integrations. Confirm whether it is used before blocking.
Protect login
Common controls:
- Limit login attempts (plugin or WAF)
- Enable 2FA for admin users
- Use strong passwords and disable unused admin accounts
- Consider moving admin access behind VPN/bastion for private sites
Anti-DDoS tuning for OpenLiteSpeed + WordPress
Prioritize cheap rejections
- Reject oversized bodies at the web server before PHP runs
- Cache public pages aggressively (LiteSpeed Cache plugin where appropriate)
- Rate limit expensive dynamic endpoints and admin routes
- Use a CDN for static assets and consider caching HTML where safe
Cache policy notes
- Ensure
Varyheaders are correct (mobile, logged-in users). - Do not cache personalized pages (cart/checkout/account).
- Use origin shielding where possible (CDN features).
Practical scenarios and impacts (misconfigurations)
Scenario 1: Web server request limit lower than PHP upload limit
| Wrong configuration | Example | Impact |
|---|---|---|
| -- | ||
| Web server rejects body before PHP sees it | OLS max body 32M, PHP upload_max_filesize=64M | Uploads fail with 4xx errors; WordPress shows generic upload error |
Fix:
- Increase web server max body or reduce PHP limits so they match.
Scenario 2: post_max_size lower than upload_max_filesize
| Wrong configuration | Example | Impact |
|---|---|---|
| - | - | - |
| PHP rejects POST even though file limit is higher | post_max_size=32M, upload_max_filesize=64M | Uploads fail inconsistently; large forms break |
Fix:
- Set
post_max_size>=upload_max_filesizewith overhead (multipart/form-data adds overhead).
Scenario 3: Rate limiting applied to CDN IPs instead of real clients
| Wrong configuration | Example | Impact |
|---|---|---|
| - | -- | -- |
| Origin sees only proxy IP, so all users share one “client” | Rate limit keyed on REMOTE_ADDR while behind CDN | Legit traffic gets blocked during peaks; false positives |
Fix:
- Configure trusted proxy headers and real client IP handling (varies by CDN and OLS settings).
- Only trust headers from known proxy ranges.
Scenario 4: Overly aggressive limits on admin-ajax and REST
| Wrong configuration | Example | Impact |
|---|---|---|
| - | -- | |
| Rate limits block legitimate dynamic requests | Tight RPS limits on /wp-admin/admin-ajax.php | Checkout, carts, and dynamic widgets break; admin UI errors |
Fix:
- Apply different limits for authenticated users/admin IP ranges versus public clients.
- Measure endpoint usage before enforcing strict blocks.
Scenario 5: Blocking large requests breaks backups/migrations
| Wrong configuration | Example | Impact |
|---|---|---|
| - | - | -- |
| Request limits too small for zip imports | max body 32M but migration needs 256M | Backup restore fails; site migration blocked |
Fix:
- Use an alternate transfer method (SFTP/SSH + server-side restore) for large backups.
- Temporarily raise limits during maintenance windows only.
Scenario 6: “Anti-DDoS” rules cause self-inflicted downtime
| Wrong configuration | Example | Impact |
|---|---|---|
| -- | - | |
| Low connection/timeouts block normal users | Very low keepalive or request timeouts | Increased 499/408 errors, higher load due to retries |
Fix:
- Tune timeouts based on real traffic and TLS overhead.
- Avoid lowering timeouts below typical client behavior.
Troubleshooting
Identify whether failures happen at web server, PHP, or WordPress
- Reproduce with headers (read-only request):
curl -I https://example.com
-
Test an upload path with a known size file (from a trusted admin machine).
-
Check logs:
- OpenLiteSpeed access/error logs (paths vary by config)
- PHP error log
- WordPress debug log (if enabled)
- Confirm effective PHP limits:
php -i | grep -E 'upload_max_filesize|post_max_size|max_input_time|max_execution_time|memory_limit'
Common indicators:
| Symptom | Likely layer |
|---|---|
| - | - |
| Immediate 413/4xx on upload | Web server request body limit |
| PHP warnings/fatals about POST size | PHP post_max_size |
| WordPress UI says “upload failed” but logs show 413/4xx | Web server limit |
| 502/503 spikes under traffic | LSAPI workers, rate limits, CPU/RAM exhaustion |
Security notes
Anti-DDoS and request-size limits must be layered. A single misconfigured layer can either block legitimate users or allow expensive traffic into PHP/DB where it is most damaging.
Recommended baseline:
- Tight request body limits for public endpoints
- Separate higher upload limits only where needed (admin-only or authenticated upload paths)
- CDN in front of the origin where feasible
- Rate limiting for login, XML-RPC, REST, and admin-ajax
- Monitoring for 4xx/5xx rates and server memory pressure
Quick reference
Size alignment
| Setting | Rule |
|---|---|
| - | - |
| Web server max body | Must be >= PHP post_max_size |
PHP post_max_size | Must be >= PHP upload_max_filesize (+ overhead) |
| WordPress uploads | Fail if any upstream layer is smaller |
Common PHP knobs
upload_max_filesize = 48M
post_max_size = 64M
max_input_time = 60
max_execution_time = 120
max_file_uploads = 20
Safe diagnostics
free -h
vmstat 1 5
php -i | grep -E 'upload_max_filesize|post_max_size|max_input_time|max_execution_time|memory_limit'
sudo ss -lntp | grep -E ':(80|443)\b' || true